using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace IntensityGraph
{
    public delegate void ResolutionChanged(int x,int y);

    public partial class IntensityGraph : UserControl
    {

        public event ResolutionChanged OnResolutionChanged;

        #region Private Stuff
        private int _XRes = 32;
        private int _YRes = 32;
   
        //How much of a "cell" should be a pixel vs interspace
        private float _RelativePixelSizeX = 0.75f;
        private float _RelativePixelSizeY = 0.75f;

        private Color _MaxColor = Color.White;
        private Color _MinColor = Color.Black;

        private Brush _BGBrush = new SolidBrush(Color.FromArgb(60, 60, 60));
        private Color _BGColor;

        byte [,] DataPlane;

        #endregion

        public IntensityGraph()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            XRes = 8;
            YRes = 8;
            RelativePixelSizeX = 0.75f;
            RelativePixelSizeY = 0.75f;
            ReinitBitPlanes();
        }

        public void SetData(byte[,] NewData)
        {
            if (NewData.GetLength(0) == _XRes && NewData.GetLength(1) == _YRes)
            {
                DataPlane = NewData;
                this.Invalidate();
            }
       }

        public Color BGColor
        {
            set
            {
                _BGColor = value;
                _BGBrush = new SolidBrush( _BGColor);
                this.Invalidate();
            }

            get
            {
                return _BGColor;
            }

        }
        private void ReinitBitPlanes()
        {
           
            DataPlane = new byte[XRes,YRes];
       
           
            for (int x = 0; x < XRes; x++)
            {
                for (int y = 0; y < YRes; y++)
                {
                    DataPlane[x, y] = (byte)(x*y);
                }
            }
        }

        public Color MaxColor
        {
            get { return _MaxColor;  }
            set { _MaxColor = value; this.Invalidate(); }
        }

        public Color MinColor
        {
            get { return _MinColor;  }
            set { _MinColor = value; this.Invalidate(); }
        }

        public int XRes
        {
            get
            {
                return _XRes;
            }
            set
            {
                if (value > 1)
                {
                    _XRes = value;
                    ReinitBitPlanes();
                    this.Invalidate();
                    if (OnResolutionChanged != null)
                        OnResolutionChanged(_XRes, _YRes);
                }
               
            }
        }

        public int YRes
        {
            get
            {
                return _YRes;
            }
            set
            {

                if (value > 1)
                {
                    _YRes = value;
                    ReinitBitPlanes();
                    this.Invalidate();

                    if (OnResolutionChanged != null)
                        OnResolutionChanged(_XRes, _YRes);
                }
            }
        }

        

        public float RelativePixelSizeX
        {
            get
            {
                return _RelativePixelSizeX;
            }
            set
            {
                if (_RelativePixelSizeX > 1.0f)
                {
                    _RelativePixelSizeX = 1.0f;
                }
                else if(_RelativePixelSizeX < 0.1f)
                {
                    _RelativePixelSizeX = 0.1f;
                }
                else
                {
                _RelativePixelSizeX = value;
                }
                this.Invalidate();
            }
        }

        public float RelativePixelSizeY
        {
            get
            {
                return _RelativePixelSizeY;
            }
            set
            {
                if (_RelativePixelSizeY > 1.0f)
                {
                    _RelativePixelSizeY = 1.0f;
                }
                else if(_RelativePixelSizeY < 0.1f)
                {
                    _RelativePixelSizeY = 0.1f;
                }
                else
                {
                     _RelativePixelSizeY = value;
                }
                this.Invalidate();
            }
        }
        private float XCellSize
        {
            get
            {
                return (float)this.Size.Width / (float)_XRes;
            }

        }
        private float YCellSize
        {
            get
            {
                return (float)this.Size.Height / (float)_YRes;
            }
        }

        private float XPixelSize
        {
            get
            {
                return XCellSize* _RelativePixelSizeX;
            }
        }
        private float YPixelSize
        {
            get
            {
                return YCellSize * _RelativePixelSizeY;
            }
        }

        private float XOffset
        {
            get
            {
                return (XCellSize - XPixelSize) / 2.0f;
            }
        }
        private float YOffset
        {
            get
            {
                return (YCellSize - YPixelSize) / 2.0f;
            }
        }

     

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            e.Graphics.FillRectangle(_BGBrush, this.ClientRectangle);

         

            for (int x = 0; x < _XRes; x++)
            {
                for (int y = 0; y < _YRes; y++)
                {

                    byte CurrentVal = DataPlane[x, y];

                    byte Ri, Gi, Bi;

                    Ri = (byte)((_MaxColor.R-_MinColor.R)*((double)(CurrentVal)/(255.0)) +_MinColor.R);
                    Gi = (byte)((_MaxColor.G - _MinColor.G) * ((double)(CurrentVal) / (255.0)) + _MinColor.G);
                    Bi = (byte)((_MaxColor.B - _MinColor.B) * ((double)(CurrentVal) / (255.0)) + _MinColor.B);
                    
                    Brush RenderColor = new SolidBrush(Color.FromArgb(Ri,Gi,Bi));

                    e.Graphics.FillRectangle(RenderColor, XOffset + (x * XCellSize),
                                            YOffset + (y * YCellSize), XPixelSize, YPixelSize);
                }

            }

        }

        private void BiColorLEDDisplay_Load(object sender, EventArgs e)
        {

        }

    }
}